unit firstscanhandler;

interface

uses windows,classes,sysutils;

type TFirstscantype= (fs_advanced,fs_addresslist);
type TValueType= (vt_byte,vt_word, vt_dword, vt_single, vt_double, vt_int64);

type TFirstScanHandler = class
  private
    firstscanmemory: tmemorystream;
    firstscanaddress: tmemorystream;
    firstscantype: tfirstscantype;
    function getpointertoaddress(address:dword;valuetype:tvaluetype): pointer;
  public
    function getfirstscanbyte(address: dword): byte;
    function getfirstscanword(address: dword): word;
    function getfirstscandword(address: dword): dword;
    function getfirstscansingle(address: dword): single;
    function getfirstscandouble(address: dword): double;
    function getfirstscanint64(address: dword): int64;

    constructor create;
    destructor destroy; override;
end;


implementation

uses Luan1;

function TFirstScanHandler.getpointertoaddress(address:dword;valuetype:tvaluetype): pointer;
type TArrMemoryRegion= array [0..0] of TMemoryRegion;
var i,j: integer;
    pm: ^TArrMemoryRegion;
    pa: PDwordArray;
    p: pbyte;
    p1: PByteArray;
    p2: PWordArray;
    p3: PDwordArray;
    p4: PSingleArray;
    p5: PDoubleArray;
    p6: PInt64Array;
begin
  result:=nil;

  p:=firstscanaddress.Memory;
  inc(p,7);

  if firstscantype=fs_advanced then
  begin
    //the addressfile exists out of a list of memoryregions
    pm:=pointer(p);

    j:=(firstscanaddress.Size-7) div sizeof(TMemoryRegion); //max number of regions

    p:=firstscanmemory.Memory;
    for i:=0 to j-1 do
    begin
      if (address>=pm[i].baseaddress) and (address < (pm[i].BaseAddress + pm[i].MemorySize)) then
      begin
        inc(p,address-pm[i].baseaddress);
        result:=p;
        exit;
      end;
      inc(p,pm[i].MemorySize);
    end;
  end
  else
  begin
    //the addressfile exists out of a list of addresses
    pa:=pointer(p);
    j:=(firstscanaddress.Size-7) div sizeof(dword); //max number of addresses
    p1:=firstscanmemory.Memory;
    p2:=firstscanmemory.Memory;
    p3:=firstscanmemory.Memory;
    p4:=firstscanmemory.Memory;
    p5:=firstscanmemory.Memory;
    p6:=firstscanmemory.Memory;
    for i:=0 to j-1 do
    begin
      if (address<=pa[i]) then
      begin
        if address=pa[i] then
        begin
          case valuetype of
            vt_byte : result:=@p1[i];
            vt_word : result:=@p2[i];
            vt_dword : result:=@p3[i];
            vt_single: result:=@p4[i];
            vt_double: result:=@p5[i];
            vt_int64: result:=@p6[i];
          end;

          exit;
        end
        else exit; //not found
      end;
    end;
  end;
end;

function TFirstScanHandler.getfirstscanbyte(address: dword): byte;
begin
  result:=pbyte(getpointertoaddress(address,vt_byte))^; //tries to read nil is not found, which should never happen, so I should get a bug report if it does
end;

function TFirstScanHandler.getfirstscanword(address: dword): word;
begin
  result:=pword(getpointertoaddress(address,vt_word))^; //tries to read nil is not found, which should never happen, so I should get a bug report if it does
end;

function TFirstScanHandler.getfirstscandword(address: dword): dword;
begin
  result:=pdword(getpointertoaddress(address,vt_dword))^; //tries to read nil is not found, which should never happen, so I should get a bug report if it does
end;

function TFirstScanHandler.getfirstscansingle(address: dword): single;
begin
  result:=psingle(getpointertoaddress(address,vt_single))^; //tries to read nil is not found, which should never happen, so I should get a bug report if it does
end;

function TFirstScanHandler.getfirstscandouble(address: dword): double;
begin
  result:=pdouble(getpointertoaddress(address,vt_double))^; //tries to read nil is not found, which should never happen, so I should get a bug report if it does
end;

function TFirstScanHandler.getfirstscanint64(address: dword): int64;
begin
  result:=pint64(getpointertoaddress(address,vt_int64))^; //tries to read nil is not found, which should never happen, so I should get a bug report if it does
end;


constructor TFirstScanHandler.create;
var datatype: string[6];
begin
  firstscanmemory:=tmemorystream.Create;
  try
    firstscanmemory.LoadFromFile(cheatenginedir+'MEMORYFIRST.TMP');
  except
    firstscanmemory.Free;
    raise exception.Create('No first scan data files found');
  end;

  firstscanaddress:=tmemorystream.Create;
  try
    firstscanaddress.LoadFromFile(cheatenginedir+'ADDRESSESFIRST.TMP');
  except
    firstscanmemory.Free;
    firstscanaddress.free;
    raise exception.Create('No first scan data files found');
  end;

  firstscanaddress.ReadBuffer(datatype,7);
  if datatype='REGION' then firstscantype:=fs_advanced else firstscantype:=fs_addresslist;
end;

destructor TFirstScanHandler.destroy;
begin
  firstscanmemory.free;
  firstscanaddress.free;
  inherited destroy;
end;

end.
